'use strict';

const path = require('path');

let pkgDir, pathExists;
const npminstall = require('npminstall');
const fse = require('fs-extra');

const { isObject } = require('@nz-cli/utils');
const formatPath = require('@nz-cli/format-path');
const { getDefaultRegistry, getNpmLatestVersion } = require('@nz-cli/get-npm-info');
const log = require('@nz-cli/log');

class Package {
  constructor(options) {
    if ( !options ) {
      throw new Error('Package类的options参数不能为空! ')
    }
    if (!isObject(options) ) {
      throw new Error('Package类的options参数必须为对象! ')
    }
    // package路径
    this.targetPath = options.targetPath;
    // 缓存 package 的路径
    this.storeDir = options.storeDir;
    this.packageName = options.packageName;
    this.packageVersion = options.packageVersion;
  }

  async prepare() {
    if (!pathExists) {
      const pathExistsObj = await import('path-exists');
      pathExists = pathExistsObj.pathExistsSync;
    }
    if (this.storeDir && !pathExists(this.storeDir)) {
      // mkdirp 将 这个路径上 不存在的目录 都创建好
      fse.mkdirpSync(this.storeDir);
    }
    if (this.packageVersion === 'latest') {
      // 获取package的最新版本号
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
  }

  // 获取 package 缓存文件的 所在目录的路径
  get cacheFilePath() {
    return path.resolve(this.storeDir, this.packageName)
  }

  // 获取指定的版本号的 package 的路径
  getSpecificCacheFilePath(packageVersion) {
    return path.resolve(this.storeDir, `\.store\\${this.packageName.replace(/\//, '+')}@${packageVersion}\\node_modules\\${this.packageName}`)
  }

  // 判断当前 Package 是否存在
  async exists() {
    const pathExistsObj = await import('path-exists');
    pathExists = pathExistsObj.pathExistsSync;
    if (this.storeDir) {
      // 缓存模式
      await this.prepare();
      log.verbose('cacheFilePath', this.cacheFilePath)
      return pathExists(this.cacheFilePath);
    } else {
      return pathExists(this.targetPath);
    }
  }

  // 安装 Package
  async install() {
    await this.prepare();
    return npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(),
      pkgs: [
        { name: this.packageName, version: this.packageVersion }
      ]
    })
  }

  // 更新 Package
  async update() {
    await this.prepare();
    const latestPackageVersion = await getNpmLatestVersion(this.packageName);
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion);
    log.verbose('latestFilePath', latestFilePath)
    // 检查缓存路径是否存在 package 的最新版本
    if (!pathExists(latestFilePath)) {
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(),
        pkgs: [
          { name: this.packageName, version: latestPackageVersion }
        ]
      })
      this.packageVersion = latestPackageVersion;
    }
  }

  // 获取入口文件的路径
  async getRootFilePath() {
    const { packageDirectorySync } = await import('pkg-dir');
    pkgDir = packageDirectorySync;
    const _getRootFile = tp => {
      // 获取package.json所在目录
      const dir = pkgDir({ cwd: tp });
      if (dir) {
        const pkgFile = require(path.resolve(dir, 'package.json'))
        if (pkgFile && pkgFile.main) {
          // 返回入口文件的路径
          return formatPath(path.resolve(dir, pkgFile.main))
        }
      }
      return null;
    }
    if (this.storeDir) {
      return _getRootFile(this.cacheFilePath)
    } else {
      return _getRootFile(this.targetPath);
    } 
  }

}

module.exports = Package;
